package com.zx.video28181.activity;

import android.Manifest;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.javax.sip.InvalidArgumentException;
import android.javax.sip.SipException;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import com.zx.video28181.R;
import com.zx.video28181.domain.Device;
import com.zx.video28181.sip.ClientListener;
import com.zx.video28181.sip.SipStackAndroid;

import java.io.File;
import java.io.FileOutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;

public class MainActivity extends AppCompatActivity
        implements View.OnClickListener, QualityDialog.VideoLevelCallBack, ClientListener.InitAboutCamera,
        SurfaceHolder.Callback {

    private static final String TAG = "Camera";
    private Camera camera;
    private View transitionBg;
    private LinearLayout llRegister;
    private FileOutputStream outputStream1;
    private FileOutputStream outputStream2;
    private TextView tvFrameSize;
    // 开启和停止直播转换
    private TextView tvstartorstop;
    private ImageView tvstartorstopimage;
    private ImageView ivCamera;
    private TextView ivSetting;
    private EditText etDeviceId, etPsw, etServerIp, etPort, etServerId;
    private LinearLayout top_tool_bar;
    // 定义对象
    private SurfaceView mSurfaceview = null;
    private SurfaceHolder mSurfaceHolder = null;
    private boolean bIfPreview = false;//正在预览
    private int mPreviewWidth, mPreviewHeight;
    private QualityDialog frameDialog;
    private List<Camera.Size> previewSizes;
    private List<Camera.Size> dialogPreviewSizes;
    private Context mContext;
    private byte[] mPreviewBuffer;
    public static Map<String, Device> ds;
    String txtDeviceId = null;
    String txtPsw = null;
    String txtServerIp = null;
    String txtPort = null;
    String txtServerId = null;
    SipStackAndroid sip;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, 12);
            }
        }
        createFile();
        ds = new ConcurrentHashMap<>(1);
        initSurfaceView();
//        checkPermission();
        // 取消耗时操作不能再主线程进行校验
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        setupView();
        //应用运行时，保持屏幕高亮，不锁屏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    private void initSurfaceView() {
        Log.d(TAG, "initSurfaceView: start");
//        mSurfaceview= findViewById(R.id.sv_preview);
//        mSurfaceHolder = mSurfaceview.getHolder();
//        mSurfaceHolder.addCallback(this);
        mSurfaceview = this.findViewById(R.id.sv_preview);
        mSurfaceview.setOnClickListener(this);

        mSurfaceHolder = mSurfaceview.getHolder(); // 绑定SurfaceView，取得SurfaceHolder对象
        mSurfaceHolder.addCallback(this); // SurfaceHolder加入回调接口
        // mSurfaceHolder.setFixedSize(176, 144); // 预览大小設置
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 設置顯示器類型，setType必须设置
        Log.d(TAG, "initSurfaceView: stop");
    }


    private void setupView() {
        top_tool_bar = findViewById(R.id.top_tool_bar);
        etDeviceId = findViewById(R.id.et_device_id);
        etPsw = findViewById(R.id.et_psw);
        etServerIp = findViewById(R.id.et_server_ip);
        etPort = findViewById(R.id.et_port);
        etServerId = findViewById(R.id.et_server_id);
        tvFrameSize = findViewById(R.id.tv_frame_size);
        ivCamera = findViewById(R.id.iv_camera);
        ivSetting = findViewById(R.id.tv_setting);
        transitionBg = findViewById(R.id.transition_bg);
        llRegister = findViewById(R.id.ll_register_layer);
        tvstartorstop = findViewById(R.id.tv_start_stop);
        tvstartorstopimage = findViewById(R.id.tv_start_stop_image);
        transitionBg.setVisibility(View.GONE);
        llRegister.setVisibility(View.GONE);
        transitionBg.setOnClickListener(this);
        tvFrameSize.setOnClickListener(this);
        tvstartorstop.setOnClickListener(this);
        ivCamera.setOnClickListener(this);
        ivSetting.setOnClickListener(this);
        findViewById(R.id.txt_login).setOnClickListener(this);
        GB28181Params.setSIPServerIPAddress(etServerIp.getText().toString());
        GB28181Params.setRemoteSIPServerPort(Integer.parseInt(etPort.getText().toString()));
        GB28181Params.setRemoteSIPServerID(etServerId.getText().toString());
        GB28181Params.setLocalSIPDeviceId("22012200011124476055");
        GB28181Params.setLocalSIPMediaId("22012200011324476055");
        GB28181Params.setLocalSIPIPAddress("192.168.10.11");
        GB28181Params.setLocalSIPPort(5099);


    }

    private boolean test = false;

    void sendAboutSip() {
        // 初始化udp及注册请求发起
        Log.d(TAG, "sendAboutSip: " + etServerIp.getText().toString());
        try {

            Device device = new Device();
            device.setDeviceId("22012200011124476055");
            device.setDeviceId(GB28181Params.getLocalSIPDeviceId());
            ds.put(device.getDeviceId(), device);
            Device deviceMedia = new Device();
            deviceMedia.setDeviceId("22012200011324476055");
            deviceMedia.setDeviceId(GB28181Params.getLocalSIPMediaId());
            ds.put(deviceMedia.getDeviceId(), deviceMedia);
            sip.sendMessage(GB28181Params.REGISTER);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.tv_setting) {
            llRegister.setVisibility(View.VISIBLE);
            transitionBg.setVisibility(View.GONE);
        } else if (view.getId() == R.id.txt_login) {
            Log.d(TAG, "setupView: " + etServerIp.getText().toString());
//            checkLoginData();
            // 初始化基础参数
            setupView();
            Log.d(TAG, "setupView: " + etServerIp.getText().toString());
        } else if (view.getId() == R.id.tv_frame_size) {
//            if (loginStatus == 2) {
//                Toast.makeText(mContext, "连接中不可以切换分辨率", Toast.LENGTH_LONG).show();
//                return;
//            }
            if (frameDialog == null) {
                frameDialog = new QualityDialog(mContext);
            }
            frameDialog.setLevelCallBack(this);
            frameDialog.setPreviewSizes(dialogPreviewSizes);
            frameDialog.setCancelable(true);
            frameDialog.show();
        } else if (view.getId() == R.id.tv_start_stop) {
            if (tvstartorstop.getText().toString().equals("开启直播")) {
                tvstartorstop.setText("停止直播");
                Drawable drawable = getResources().getDrawable(R.mipmap.stopzhibo);
                tvstartorstopimage.setBackgroundDrawable(drawable);
                // 初始化sip
                try {
                    if (!test) {
                        sip = new SipStackAndroid(etServerIp.getText().toString(), mPreviewBuffer, this);
                    }
                    test = true;
                } catch (Exception e) {
                    e.printStackTrace();
                }
                sendAboutSip();
            } else {
                tvstartorstop.setText("开启直播");
                Drawable drawable = getResources().getDrawable(R.mipmap.startzhibo);
                tvstartorstopimage.setBackgroundDrawable(drawable);

//                initCamera();
                try {
                    MainActivity.ds.remove("22012200011124476055");
                    MainActivity.ds.remove(GB28181Params.getLocalSIPDeviceId());
                    sip.sendMessage(GB28181Params.CANCEL);
                } catch (ParseException | InvalidArgumentException | SipException e) {
                    e.printStackTrace();
                }

            }
        } else if (view.getId() == R.id.iv_camera) {

            if (currentCameraType == BACK) {
                currentCameraType = FRONT;
            } else {
                currentCameraType = BACK;
            }
            setupCamera();
            initCamera();
        }
    }

    private void checkPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {

            } else {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, 12);
            }
        }
    }

    private Boolean checkLoginData() {
        txtDeviceId = etDeviceId.getText().toString();
        txtPsw = etPsw.getText().toString();
        txtServerIp = etServerIp.getText().toString();
        txtPort = etPort.getText().toString();
        txtServerId = etServerId.getText().toString();

        if (TextUtils.isEmpty(txtDeviceId)) {
            Toast.makeText(mContext, "设备ID不能为空 ", Toast.LENGTH_LONG).show();
            return false;
        }

        if (TextUtils.isEmpty(txtPsw)) {
            Toast.makeText(mContext, "密码不能为空", Toast.LENGTH_LONG).show();
            return false;
        }
        if (TextUtils.isEmpty(txtServerIp)) {
            Toast.makeText(mContext, "服务器IP不能为空", Toast.LENGTH_LONG).show();
            return false;
        }
        if (TextUtils.isEmpty(txtPort)) {
            Toast.makeText(mContext, "服务器端口不能为空", Toast.LENGTH_LONG).show();
            return false;
        }
        if (TextUtils.isEmpty(txtServerId)) {
            Toast.makeText(mContext, "服务器ID不能为空", Toast.LENGTH_LONG).show();
            return false;
        }

        transitionBg.setVisibility(View.GONE);
        llRegister.setVisibility(View.GONE);

        return true;
    }

    @Override
    public void setVideoLevel(int Level) {
        Camera.Size mSize = dialogPreviewSizes.get(Level);
        mPreviewWidth = mSize.width;
        mPreviewHeight = mSize.height;
        tvFrameSize.setText(mPreviewWidth + "x" + mPreviewHeight);
        setupCamera();
        initCamera();
    }

    private void setupCamera() {
        releaseCamera();
        checkPermission();
        Log.d(TAG, "setupCamera: start");
        if (checkCameraDisabled()) return;

        int frontIndex = -1;
        int backIndex = -1;

        int cameraCount = Camera.getNumberOfCameras();
        Camera.CameraInfo info = new Camera.CameraInfo();

        for (int cameraIndex = 0; cameraIndex < cameraCount; cameraIndex++) {
            Camera.getCameraInfo(cameraIndex, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                frontIndex = cameraIndex;
            } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                backIndex = cameraIndex;
            }
        }

        if (currentCameraType == BACK) {
            camera = Camera.open(backIndex);// 开启摄像头（2.3版本后支持多摄像头,需传入参数）0为后置 1为前置
        } else if (currentCameraType == FRONT) {
            camera = Camera.open(frontIndex);// 开启摄像头（2.3版本后支持多摄像头,需传入参数）0为后置 1为前置
        }
        GB28181Params.setmCamera(camera);
        try {
            Log.i(TAG, "SurfaceHolder.Callback：surface Created");
            camera.setPreviewDisplay(mSurfaceHolder);//set the surface to be used for live preview
        } catch (Exception ex) {
            if (null != camera) {
                camera.release();
                camera = null;
            }
            Log.i(TAG, ex.getMessage());
        }
        Log.d(TAG, "setupCamera: stop");
    }

    private static final int FRONT = 1;//前置摄像头标记
    private static final int BACK = 2;//后置摄像头标记

    private int currentCameraType = BACK;//当前打开的摄像头标记

    private void releaseCamera() {
        if (bIfPreview && camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();//stopCamera();
            camera.release();
            camera = null;
        }
    }

    private boolean checkCameraDisabled() {
        DevicePolicyManager dpm = (DevicePolicyManager) MainActivity.this.getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        return dpm.getCameraDisabled(null);
    }

    private void initCamera() {
        Log.i(TAG, "going into initCamera");
        if (null == camera) {
            return;
        }
        try {
            /* Camera Service settings*/
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPictureFormat(PixelFormat.JPEG); //Sets the image format for picture 设定相片格式为JPEG，默认为NV21
            parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); //Sets the image format for preview picture，默认为NV21
            previewSizes = parameters.getSupportedPreviewSizes();
            List<Integer> previewFormats = parameters.getSupportedPreviewFormats();
            parameters.setPreviewFrameRate(30);
            Log.i(TAG + "initCamera", "gyz support parameters is ");
            Camera.Size psize = null;
            dialogPreviewSizes = new ArrayList<>();
            for (Camera.Size previewSize : previewSizes) {

                if ((previewSize.width == 1280 && previewSize.height == 720)
                        || (previewSize.width == 960 && previewSize.height == 540)
                        || (previewSize.width == 640 && previewSize.height == 480)) {
                    dialogPreviewSizes.add(previewSize);
                }
            }

            for (int i = 0; i < dialogPreviewSizes.size() && mPreviewWidth == 0 && mPreviewHeight == 0; i++) {
                psize = dialogPreviewSizes.get(i);
                Log.i(TAG + "initCamera", "PreviewSize,width: " + psize.width + " height" + psize.height);
                mPreviewWidth = psize.width;
                mPreviewHeight = psize.height;
                break;
            }
            mPreviewBuffer = new byte[mPreviewWidth * mPreviewHeight * 3 / 2];
            GB28181Params.setCameraWidth(mPreviewWidth);
            GB28181Params.setCameraHeigth(mPreviewHeight);

            Integer pf = null;
            for (int i = 0; i < previewFormats.size(); i++) {
                pf = previewFormats.get(i);
                Log.i(TAG + "initCamera", "previewformates:" + pf);
            }
            Camera.Size previewSize = getCameraPreviewSize(parameters);
//             width = previewSize.width;
//             height = previewSize.height;
//            //设置预览格式（也就是每一帧的视频格式）YUV420下的NV21
            parameters.setPreviewFormat(ImageFormat.NV21);
//            //设置预览图像分辨率
            parameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
            camera.setDisplayOrientation(90);
            //配置camera参数
            camera.setParameters(parameters);
            /* 视频流编码处理 */
            //添加对视频流处理函数
            // 设定配置参数并开启预览
            camera.setParameters(parameters); // 将Camera.Parameters设定予Camera
            tvFrameSize.setText(mPreviewWidth + "x" + mPreviewHeight);
            camera.startPreview(); // 打开预览画面
            camera.cancelAutoFocus();// 2如果要实现连续的自动对焦，这一句必须加上
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取设备支持的最大分辨率
     */
    private Camera.Size getCameraPreviewSize(Camera.Parameters parameters) {
        List<Camera.Size> list = parameters.getSupportedPreviewSizes();
        Camera.Size needSize = null;
        for (Camera.Size size : list) {
            if (needSize == null) {
                needSize = size;
                continue;
            }
            if (size.width >= needSize.width) {
                if (size.height > needSize.height) {
                    needSize = size;
                }
            }
        }
        return needSize;
    }

    private void createFile() {
        File file = new File(getExternalCacheDir(), "test.h264");
        File file2 = new File(getExternalCacheDir(), "test1.h264");
        try {
            outputStream1 = new FileOutputStream(file);
            outputStream2 = new FileOutputStream(file2);
            GB28181Params.setFileOutPutStream1(outputStream1);
            GB28181Params.setFileOutPutStream2(outputStream2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void surfaceCreated(SurfaceHolder holder) {
        setupCamera();
//        openCamera();
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 当SurfaceView/预览界面的格式和大小发生改变时，该方法被调用
        Log.i(TAG, "SurfaceHolder.Callback：Surface Changed");
        initCamera();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // SurfaceView销毁时，该方法被调用
        Log.i(TAG, "SurfaceHolder.Callback：Surface Destroyed");
        if (null != camera) {
            camera.setPreviewCallback(null); //！！这个必须在前，不然退出出错
            camera.stopPreview();
            bIfPreview = false;
            camera.release();
            camera = null;
        }
    }


    @Override
    public void initAboutCamera() {
//        setupCamera();
        initCamera();
    }
}